package com.free.bsf.sentinel;

import com.free.bsf.core.base.BsfException;
import com.free.bsf.core.base.Ref;
import com.free.bsf.core.util.PropertyUtils;
import com.free.bsf.sentinel.base.SphEntry;
import lombok.val;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

/**
 * @Classname FeignClient限流拦截
 * @Description
 * @Date 2021/4/28 10:03
 * @Created by chejiangyi
 */
@Aspect
public class FeignClientSentinelAspect {
    @Pointcut("@within(org.springframework.cloud.openfeign.FeignClient)")
    public void pointCut(){};

    @Around("pointCut()")
    public Object handle(ProceedingJoinPoint joinPoint) throws Throwable {
        val method = ((MethodSignature)joinPoint.getSignature()).getMethod();
        val uri = method.getDeclaringClass().getName()+"."+method.getName();
        val includeResource = PropertyUtils.getPropertyCache(SentinelProperties.BsfSentinelFeignIncludeResource,"");
        boolean isInclude = SentinelUtils.isLikeMatch(uri,includeResource.replace("feign:","").split(";"));
        if(isInclude) {
            Ref<Throwable> ex = new Ref<>(null);
            Ref<Object> result = new Ref<>(null);
            SentinelUtils.run(new SphEntry().setName("feign:" + uri), () -> {
                try {
                    result.setData(joinPoint.proceed());
                } catch (Throwable e) {
                    ex.setData(e);
                }
            });
            if (ex.getData() != null) {
                throw new BsfException(ex.getData());
            }
            return result.getData();
        }else {
            return joinPoint.proceed();
        }
    }

}
